﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Bouyei.NetFactoryCore.Providers.WebSocket
{
    using Protocols.WebSocketProt;
    using Base;

    public class WSServerProvider
    {
        public WSServerProvider()
        {

        }

        #region handshake
        private ClientAccessInfo HandshakeResolveClient(SegmentOffset segOffset)
        {
            string msg = Encoding.UTF8.GetString(segOffset.buffer, segOffset.offset, segOffset.size);
            string[] items = msg.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
            if (items.Length < 8)
                throw new Exception("access format error..." + msg);

            return new ClientAccessInfo()
            {
                HttpProt = items[0],
                Connection = items[1].Split(':')[1],
                Host = items[2].Split(':')[1],
                Orgin = items[3].Split(':')[1],
                SecExtensions = items[4].Split(':')[1],
                SecKey = items[5].Split(':')[1],
                SecVersion = items[6].Split(':')[1],
                Upgrade = items[7].Split(':')[1]
            };
        }

        private ServerAccessInfo HandshakePackageServer(ClientAccessInfo info)
        {
            return new ServerAccessInfo()
            {
                HttpProt = info.HttpProt,
                Connection = info.Connection,
                Server = "bouyei websocket server",
                Upgrade = info.Upgrade,
                Date = DateTime.Now,
                AccessCredentials = true,
                AccessHeader = "content-type",
                SecAccept = info.SecKey.ToSha1Base64()
            };
        }
        #endregion

        #region resolve package

        private WebSocketPacket ResolvePayload(SegmentOffset segOffset)
        {
            if (segOffset.size < 2) return null;

            int pos = segOffset.offset;
            WebSocketPacket wsPacket = new WebSocketPacket()
            {
                Fin = (segOffset.buffer[pos] >> 7) == 1,
                OpCode = (byte)(segOffset.buffer[pos] & 0xf),
                Mask = (segOffset.buffer[++pos] >> 7) == 1,
                PayloadLength = (byte)(segOffset.buffer[pos] & 0x7f)
            };

            ++pos;
            //数据包长度超过126，需要解析附加数据
            if (wsPacket.PayloadLength == 126)
            {
                wsPacket.PayloadLength = segOffset.buffer.ToUInt16(pos);// BitConverter.ToUInt16(segOffset.buffer, pos);
                pos += 2;
            }
            else if (wsPacket.PayloadLength == 127)
            {
                wsPacket.PayloadLength = segOffset.buffer.ToUInt32(pos);
                pos += 4;
            }

            wsPacket.Payload = new SegmentOffset()
            {
                offset = pos,
                buffer = segOffset.buffer,
                size = (int)wsPacket.PayloadLength
            };

            //数据体
            if (wsPacket.Mask)
            {
                //获取掩码密钥
                wsPacket.MaskKey = new byte[4];
                wsPacket.MaskKey[0] = segOffset.buffer[pos];
                wsPacket.MaskKey[1] = segOffset.buffer[pos+1];
                wsPacket.MaskKey[2] = segOffset.buffer[pos+2];
                wsPacket.MaskKey[3] = segOffset.buffer[pos+3];
                pos += 4;

                wsPacket.Payload.offset = 0;
                wsPacket.Payload.size = (int)wsPacket.PayloadLength;
                wsPacket.Payload.buffer = new byte[wsPacket.PayloadLength];
                 
                for (int i = 0; i < wsPacket.PayloadLength; ++i)
                {
                    wsPacket.Payload.buffer[i] = (byte)(segOffset.buffer[pos] ^ wsPacket.MaskKey[i % 4]);
                }
            }

            return wsPacket;
        }

        #endregion
    }
}
